package cn.lg.soar.activiti.service.impl;

import cn.lg.soar.activiti.api.enums.ProcessStatusEnum;
import cn.lg.soar.activiti.api.enums.ResourceTypeEnum;
import cn.lg.soar.activiti.dto.ProcessDefDTO;
import cn.lg.soar.activiti.mapper.ProcessMapper;
import cn.lg.soar.activiti.service.ProcessService;
import cn.lg.soar.common.data.MapPlus;
import cn.lg.soar.common.data.MapPlusWrapper;
import cn.lg.soar.common.util.current.UserContext;
import cn.lg.soar.common.util.data.StringUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;

import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author luguoxiang
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public class ProcessServiceImpl implements ProcessService {

	private final RepositoryService repositoryService;

	private final RuntimeService runtimeService;

	private final ProcessMapper processMapper;

	public ProcessServiceImpl(RepositoryService repositoryService, RuntimeService runtimeService, ProcessMapper processMapper) {
		this.repositoryService = repositoryService;
		this.runtimeService = runtimeService;
		this.processMapper = processMapper;
	}

	/**
	 * 分页流程列表
	 * @param params
	 * @return
	 */
	@Override
	public IPage<ProcessDefDTO> getProcessByPage(Map<String, Object> params) {
		ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery()
				.processDefinitionTenantId(String.valueOf(UserContext.getUser().getCurrentTenantId())).latestVersion();

		MapPlus<String> mapPlus = new MapPlusWrapper<>(params);
		String category = mapPlus.getString("category");
		if (!StringUtil.isBlank(category)) {
			query.processDefinitionCategory(category);
			query.processDefinitionCategoryLike("%" + category + "%");
		}

		int page = mapPlus.getInteger("current");
		int limit = mapPlus.getInteger("size");

		IPage result = new Page(page, limit);
		result.setTotal(query.count());

		List<ProcessDefDTO> deploymentList = query.listPage((page - 1) * limit, limit).stream()
				.filter(processDefinition -> repositoryService.createDeploymentQuery()
						.deploymentId(processDefinition.getDeploymentId()).singleResult() != null)
				.map(processDefinition -> {
					Deployment deployment = repositoryService.createDeploymentQuery()
							.deploymentId(processDefinition.getDeploymentId()).singleResult();
					return ProcessDefDTO.toProcessDefDTO(processDefinition, deployment);
				}).collect(Collectors.toList());
		result.setRecords(deploymentList);
		return result;
	}

	/**
	 * 读取xml/image资源
	 * @param procDefId
	 * @param proInsId
	 * @param resType
	 * @return
	 */
	@Override
	public InputStream readResource(String procDefId, String proInsId, String resType) {

		if (StringUtil.isBlank(procDefId)) {
			ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(proInsId)
					.singleResult();
			procDefId = processInstance.getProcessDefinitionId();
		}
		ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
				.processDefinitionId(procDefId).singleResult();

		String resourceName = "";
		if (ResourceTypeEnum.IMAGE.getType().equals(resType)) {
			resourceName = processDefinition.getDiagramResourceName();
		}
		else if (ResourceTypeEnum.XML.getType().equals(resType)) {
			resourceName = processDefinition.getResourceName();
		}

		InputStream resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(),
				resourceName);
		return resourceAsStream;
	}

	/**
	 * 更新状态
	 * @param status
	 * @param procDefId
	 * @return
	 */
	@Override
	public Boolean updateStatus(String status, String procDefId) {
		if (ProcessStatusEnum.ACTIVE.getStatus().equals(status)) {
			repositoryService.activateProcessDefinitionById(procDefId, true, null);
		}
		else if (ProcessStatusEnum.SUSPEND.getStatus().equals(status)) {
			repositoryService.suspendProcessDefinitionById(procDefId, true, null);
		}
		return Boolean.TRUE;
	}

	/**
	 * 删除部署的流程，级联删除流程实例
	 * @param ids
	 * @return
	 */
	@Override
	public Boolean removeProcIns(String[] ids) {
		processMapper.deleteByIds(ids);
		return Boolean.TRUE;
	}

}
